Skip to content

Feature | MFAGateService (Two-Factor Gate Decision Service)#135

Open
matiasperrone-exo wants to merge 1 commit into
feat/two-factor-audit-service---cu-86ba2z5gzfrom
feat/mfa-gateservice--two-factor-gate-decision-service---cu-86ba2zfj8
Open

Feature | MFAGateService (Two-Factor Gate Decision Service)#135
matiasperrone-exo wants to merge 1 commit into
feat/two-factor-audit-service---cu-86ba2z5gzfrom
feat/mfa-gateservice--two-factor-gate-decision-service---cu-86ba2zfj8

Conversation

@matiasperrone-exo
Copy link
Copy Markdown
Contributor

Task

Ref.: https://app.clickup.com/t/86ba2zfj8

Changes

New files

  • app/Services/Auth/ITwoFactorGateService.php — Interface defining requiresChallenge(User $user, ?string $cookieToken): bool. Pure decision contract with no side effects.
  • app/Services/Auth/MFAGateService.php — Concrete implementation. Returns true only when the user requires 2FA and the device is not trusted (delegates to IDeviceTrustService).
  • tests/Unit/MFAGateServiceTest.php — 5 unit tests covering: 2FA not required, enforced with no cookie, trusted device, untrusted/expired device, and empty-string cookie passthrough.

Modified files

  • app/Services/Auth/TwoFactorServiceProvider.php — Registers ITwoFactorGateService → MFAGateService as a singleton.
  • phpunit.xml — Adds MFAGateServiceTest to the Two Factor Authentication Test Suite.

Requested GOAL

Current state

No service exists to determine whether a given login attempt requires a 2FA challenge.

Target state

MFAGateService implements a pure-decision method requiresChallenge(User $user, ?string $cookieToken): bool. It evaluates user policy and trusted-device state without writing session data, issuing OTPs, or modifying persistence.

TASKS

  • Create ITwoFactorGateService interface with:
    • requiresChallenge(User $user, ?string $cookieToken): bool
  • Implement MFAGateService.
  • requiresChallenge() logic:
    • if !$user->shouldRequire2FA(), return false
    • if user requires 2FA, call IDeviceTrustService::isDeviceTrusted($user, $cookieToken)
    • return false when device is trusted
    • return true when device is not trusted
  • Register ITwoFactorGateService in TwoFactorServiceProvider.
  • Write unit test: non-admin/non-enforced user with 2FA disabled returns false.
  • Write unit test: admin/enforced user with no cookie returns true.
  • Write unit test: admin/enforced user with trusted device returns false.
  • Write unit test: admin/enforced user with expired/revoked/wrong device returns true.

ACCEPTANCE CRITERIA

  • requiresChallenge() returns false for users who do not require 2FA.
  • requiresChallenge() returns true for users who require 2FA and have no valid trusted device.
  • requiresChallenge() returns false for users who require 2FA and have valid trusted device.
  • Method has zero side effects.
  • Method does not read cookies directly.
  • Method does not write session.
  • Method does not generate OTP.
  • Method does not persist data directly.
  • Service is injectable via ITwoFactorGateService.
  • All unit tests pass.

DEVELOPMENT NOTES

Key files:

  • New: app/Services/Auth/ITwoFactorGateService.php
  • New: app/Services/Auth/MFAGateService.php
  • New: tests/Unit/MFAGateServiceTest.php
  • Modified: app/Providers/TwoFactorServiceProvider.php

Gotchas:

  • This service is intentionally boring. Keep it as a decision point.
  • Cookie reading belongs to MFACookieManager in the controller layer.
  • Trusted-device validation belongs to DeviceTrustService.

Risks:

  • Risk: gate service starts mutating session or persistence. Mitigation: unit tests should assert only decision behavior and mocked service calls.

Out of scope:

Issuing challenges, reading HTTP request, queueing cookies, rate limiting, audit logging.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8488478e-8ccb-4214-a629-2344a829bfce

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mfa-gateservice--two-factor-gate-decision-service---cu-86ba2zfj8

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

📘 OpenAPI / Swagger preview

➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-135/

This page is automatically updated on each push to this PR.

@matiasperrone-exo matiasperrone-exo force-pushed the feat/mfa-gateservice--two-factor-gate-decision-service---cu-86ba2zfj8 branch from e65b45f to 19309fa Compare May 27, 2026 21:43
@github-actions
Copy link
Copy Markdown

📘 OpenAPI / Swagger preview

➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-135/

This page is automatically updated on each push to this PR.

@matiasperrone-exo matiasperrone-exo force-pushed the feat/mfa-gateservice--two-factor-gate-decision-service---cu-86ba2zfj8 branch from 19309fa to 25fc89f Compare May 27, 2026 21:50
@github-actions
Copy link
Copy Markdown

📘 OpenAPI / Swagger preview

➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-135/

This page is automatically updated on each push to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants